package twitterhadoop.app;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.io.WritableComparable;

@SuppressWarnings("rawtypes")
public class ClosedItemSet implements WritableComparable{
	
	private String[] itemset;
	private String[] generator;
	private String addedItem;
	int support;
	
	public String[] getItemset() {
		return itemset;
	}


	public String[] getGenerator() {
		return generator;
	}


	public int getSupport() {
		return support;
	}
	
	public String getAddedItem() {
		return this.addedItem;
	}

	public ClosedItemSet() {
		
	}
	
	/**
	 * 
	 * @param generator
	 * @param itemset
	 * @param support
	 */
	public ClosedItemSet(String[] generator, String[] itemset, int support) {
		super();
		this.generator = generator;
		this.itemset = itemset;
		this.support = support;
		this.addedItem = new String();
	}
	
	public ClosedItemSet(String[] generator, String[] itemset, String addedItem, int support) {
		super();
		this.generator = generator;
		this.itemset   = itemset;
		this.support   = support;
		this.addedItem = addedItem;
	}


	public String serialize() {
		StringBuilder s = new StringBuilder();
		s.append(StringUtils.join(itemset, ","));
		s.append(":");
		s.append(StringUtils.join(generator, ","));
		s.append(":");
		s.append(support);
		
		return s.toString();
	}
	
	public static ClosedItemSet deserialize(String line) {
		
		String[] helperArray = StringUtils.split(line, ":");
		
		String[] itemset = helperArray[0].split(",");
		String[] generator = helperArray[1].split(",");
		int support = Integer.parseInt(helperArray[2]);
		
		return new ClosedItemSet(generator, itemset, support);
	}
	
	@Override
	public String toString() {
		return "ClosedItemSet [generator=" + Arrays.toString(generator)
				+ ", itemset=" + Arrays.toString(itemset) + ", support="
				+ support + "]";
	}


	@Override
	public void readFields(DataInput in) throws IOException {
		this.generator = readStringArray(in);
		this.itemset   = readStringArray(in);
		this.addedItem = readString(in);
		this.support = in.readInt();
	}


	@Override
	public void write(DataOutput out) throws IOException {
		writeStringArray(this.generator, out);
		writeStringArray(this.itemset, out);
		writeString(this.addedItem, out);
		out.writeInt(this.support);
	}


	@Override
	public int compareTo(Object other) {
		ClosedItemSet otherCIS = (ClosedItemSet)other;
		int retVal = Reduce.compareArrays(this.generator, otherCIS.generator);
		return retVal;
	}

	/**
	 * Write a string array to output.
	 * Handles the length of the array.
	 * 
	 * @param array
	 * @param out
	 * @throws IOException
	 */
	private void writeStringArray(String[] array, DataOutput out) throws IOException {
		out.writeInt(array.length);
		for (String item : array) {
			writeString(item, out);
		}
	}
	
	private void writeString(String str, DataOutput out) throws IOException {
		out.writeInt(str.length());
		out.writeChars(str);
	}
	
	private String[] readStringArray(DataInput in) throws IOException {
		int arraySize = in.readInt();
		String[] readArray = new String[arraySize];
		for (int i = 0; i < readArray.length; i++) {
			readArray[i] = readString(in);
		}
		return readArray;
	}
	
	private String readString(DataInput in) throws IOException {
		String str = new String();
		int strLength = in.readInt();
		for (int i = 0; i < strLength; i++) {
			str = str + String.valueOf(in.readChar());
		}
		
		return str;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(generator);
		result = prime * result + Arrays.hashCode(itemset);
		result = prime * result + support;
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ClosedItemSet other = (ClosedItemSet) obj;
		if (!Arrays.equals(generator, other.generator))
			return false;
		if (!Arrays.equals(itemset, other.itemset))
			return false;
		if (support != other.support)
			return false;
		return true;
	}

}
